package com.easylinkin.linkappapi.machinery.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.additional.query.impl.LambdaQueryChainWrapper;
import com.easylinkin.linkappapi.alarm.mapper.AlarmMapper;
import com.easylinkin.linkappapi.alarm.vo.AlarmDeviceVo;
import com.easylinkin.linkappapi.common.utils.DateUtil;
import com.easylinkin.linkappapi.common.utils.NumberUtil;
import com.easylinkin.linkappapi.device.util.DeviceUtil;
import com.easylinkin.linkappapi.machinery.dto.MachineryIotDeviceDto;
import com.easylinkin.linkappapi.machinery.entity.MachineryRecord;
import com.easylinkin.linkappapi.machinery.mapper.ElevatorWorkRecordMapper;
import com.easylinkin.linkappapi.machinery.mapper.MachineryRecordMapper;
import com.easylinkin.linkappapi.machinery.mapper.TowerCraneWorkRecordMapper;
import com.easylinkin.linkappapi.machinery.service.EnterpriseMachineryService;
import com.easylinkin.linkappapi.machinery.service.MachineryNumStatisticsService;
import com.easylinkin.linkappapi.machinery.vo.ElevatorStatisticsVO;
import com.easylinkin.linkappapi.machinery.vo.ElevatorTopVO;
import com.easylinkin.linkappapi.machinery.vo.ElevatorWorkStatisticsVO;
import com.easylinkin.linkappapi.machinery.vo.MachineryDeviceVo;
import com.easylinkin.linkappapi.machinery.vo.MachineryStatisticsVO;
import com.easylinkin.linkappapi.machinery.vo.MachineryWarnGroupTypeVO;
import com.easylinkin.linkappapi.machinery.vo.ProjectStatisticsVO;
import com.easylinkin.linkappapi.machinery.vo.ProjectWarnStatsticsVO;
import com.easylinkin.linkappapi.machinery.vo.TowerCraneStatisticsVO;
import com.easylinkin.linkappapi.machinery.vo.TowerCraneTopVO;
import com.easylinkin.linkappapi.machinery.vo.TowerCraneWorkStatisticsVO;
import com.easylinkin.linkappapi.shigongyun.service.MachineryMonitorBiService;
import com.easylinkin.linkappapi.tenant.entity.LinkappTenant;
import com.easylinkin.linkappapi.tenant.mapper.LinkappTenantMapper;

import java.util.*;
import java.util.stream.Collectors;
import javax.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * @author xiaoyang
 * @version 1.0
 * @date 2022/12/07
 * @description
 */
@Slf4j
@Service
public class EnterpriseMachineryServiceImpl implements EnterpriseMachineryService {

  @Resource
  private LinkappTenantMapper linkappTenantMapper;

  @Resource
  private TowerCraneWorkRecordMapper towerCraneWorkRecordMapper;

  @Resource
  private ElevatorWorkRecordMapper elevatorWorkRecordMapper;

  @Autowired
  private MachineryMonitorBiService machineryMonitorBiService;

  @Resource
  private MachineryRecordMapper machineryRecordMapper;

  @Autowired
  private MachineryNumStatisticsService machineryNumStatisticsService;

  @Override
  public MachineryStatisticsVO getMachineryStatistics() {
    MachineryStatisticsVO statistics = new MachineryStatisticsVO();
    statistics.setTotal(0);
    statistics.setTowerCarneNum(0);
    statistics.setElevatorNum(0);
    statistics.setOther(0);
    statistics.setTowerCarneTodayWorkEfficiency(0d);
    statistics.setTowerCarneAvgEfficiency(0d);
    statistics.setTowerCarneTodayWorkCount(0);
    statistics.setTowerCarneAvgDayWorkCount(0d);
    statistics.setElevatorTodayWorkCount(0);
    statistics.setElevatorAvgDayWorkCount(0d);
    // 1.机械数量统计
    QueryWrapper<MachineryRecord> queryWrapper = new QueryWrapper<>();
    List<MachineryRecord> machineryRecords = machineryRecordMapper.selectList(queryWrapper);
    if (CollectionUtil.isNotEmpty(machineryRecords)) {
      statistics.setTotal(machineryRecords.size());
      //根据类型分组
      Map<String, List<MachineryRecord>> map = machineryRecords.stream()
          .collect(Collectors.groupingBy(m -> m.getTypeCode()));
      if (map.containsKey("QUIP_TSQZJ_01") && CollectionUtil.isNotEmpty(map.get("QUIP_TSQZJ_01"))) {
        statistics.setTowerCarneNum(map.get("QUIP_TSQZJ_01").size());
      }
      if (map.containsKey("QUIP_SJJ_02") && CollectionUtil.isNotEmpty(map.get("QUIP_SJJ_02"))) {
        statistics.setElevatorNum(map.get("QUIP_SJJ_02").size());
      }
      Integer other =
          statistics.getTotal() - statistics.getTowerCarneNum() - statistics.getElevatorNum();
      statistics.setOther(other);
    }
    // 2.塔吊统计
    // 查询所有的塔吊机械
    MachineryDeviceVo towerMachineryDeviceVo = new MachineryDeviceVo();
    towerMachineryDeviceVo.setTypeCode("QUIP_TSQZJ_01");
    List<MachineryIotDeviceDto> towerMachineryIotDeviceDtos = machineryMonitorBiService
        .selectMachineryAndDeviceByCondition(towerMachineryDeviceVo);
    if (CollectionUtil.isNotEmpty(towerMachineryIotDeviceDtos)) {

      Date yesterday = cn.hutool.core.date.DateUtil.endOfDay(cn.hutool.core.date.DateUtil.yesterday());
      Date startTime = towerMachineryIotDeviceDtos.get(0).getDeviceRefTime();
      long days = cn.hutool.core.date.DateUtil.betweenDay(startTime, yesterday, true);

      // 所有项目
      Set<String> tenantIds = towerMachineryIotDeviceDtos.stream()
          .map(MachineryIotDeviceDto::getTenantId)
          .collect(Collectors.toSet());
      // 查询塔吊总数据
      TowerCraneWorkStatisticsVO reqVO = new TowerCraneWorkStatisticsVO();
      List<String> codeList = towerMachineryIotDeviceDtos.stream()
          .map(MachineryIotDeviceDto::getDeviceCode)
          .collect(Collectors.toList());

      reqVO.setCodeList(codeList);
      reqVO.setTenantIds(tenantIds);
      // 2.1 塔吊平均工效
      /**
       * 塔吊平均工效=（所有塔吊监测最大载重之和累加/所有塔吊的总工作循环时间之和）/塔吊台数
       *   PS：不包含今日
       *   单位t/min
       */
      reqVO.setStartTime(DateUtil.getYYYYMMDDHHMMSSDate(startTime));
      reqVO.setEndTime(DateUtil.getYYYYMMDDHHMMSSDate(yesterday));
      TowerCraneWorkStatisticsVO statisticsSum1 = towerCraneWorkRecordMapper
          .getStatisticsSum(reqVO);
      if (null != statisticsSum1) {
        Integer codeSize = codeList.size();
        if (statisticsSum1.getWorkEfficiency() != null) {
          double towerCarneAvgEfficiency = NumberUtil
              .div(statisticsSum1.getWorkEfficiency(), codeSize.doubleValue(), 2);
          statistics.setTowerCarneAvgEfficiency(towerCarneAvgEfficiency);
        }
      }
      // 2.2 塔吊日平均吊装次数
      /**
       * 塔吊日平均吊装次数：
       *   【sum（每天的所有项目的吊装次数之和/每天的塔吊监测数量之和）】/塔吊监测总天数
       *   PS：不包含今日
       */
      reqVO.setStartTime(DateUtil.getYYYYMMDDHHMMSSDate(startTime));
      reqVO.setEndTime(DateUtil.getYYYYMMDDHHMMSSDate(yesterday));
      List<TowerCraneWorkStatisticsVO> statisticsByday = towerCraneWorkRecordMapper
          .getStatisticsOrderByMachineryGlobal(reqVO);
      if (CollectionUtil.isNotEmpty(statisticsByday)) {
        Map<String, List<TowerCraneWorkStatisticsVO>> dayMap = statisticsByday.stream()
            .collect(Collectors
                .groupingBy(TowerCraneWorkStatisticsVO::getDay,
                    Collectors.mapping(m -> m, Collectors.toList())));

        double avgWorkCount = 0;
        for (Map.Entry<String, List<TowerCraneWorkStatisticsVO>> entry : dayMap.entrySet()) {
          List<TowerCraneWorkStatisticsVO> dayList = entry.getValue();
          Integer machineryNumByDay = machineryNumStatisticsService
              .findMachineryNumByDay(entry.getKey(), "QUIP_TSQZJ_01");
          Integer codeNum = dayList.size();
          if(null != machineryNumByDay && 0 != machineryNumByDay){
            codeNum = machineryNumByDay;
          }
          Integer total = dayList.stream().map(TowerCraneWorkStatisticsVO::getWorkCount)
              .reduce(0, Integer::sum);
          avgWorkCount += NumberUtil.div(total.doubleValue(), codeNum.doubleValue(), 2);
        }
        if (avgWorkCount != 0 && days != 0) {
          statistics.setTowerCarneAvgDayWorkCount(NumberUtil.div(avgWorkCount, (double) days, 2));
        }

      }
      // 2.3 今日塔吊工效 2.4 今日塔吊吊装次数
      /**
       * 今日塔吊工效
       *   统计今日此时的所有项目的【（所有塔吊监测的最大载重之和）/（所有塔吊的工作循环时间之和）】/此时的塔吊监测台数
       *   工作循环时间=每次循环数据中的结束时间-开始时间
       *   单位t/min
       *
       * 今日塔吊吊装次数=统计今日此时所有项目的塔吊吊重次数
       */
      reqVO.setStartTime(DateUtil.getYYYYMMDDHHMMSSDate(DateUtil.getCurrentDayMixDate()));
      reqVO.setEndTime(DateUtil.getYYYYMMDDHHMMSSDate(DateUtil.getCurrentDayMaxDate()));
      TowerCraneWorkStatisticsVO statisticsSum2 = towerCraneWorkRecordMapper
          .getStatisticsSum(reqVO);
      if (null != statisticsSum2) {
        Integer codeSize = codeList.size();
        if (statisticsSum2.getWorkEfficiency() != null) {
          double towerCarneTodayEfficiency = NumberUtil
              .div(statisticsSum2.getWorkEfficiency(), codeSize.doubleValue(), 2);
          statistics.setTowerCarneTodayWorkEfficiency(towerCarneTodayEfficiency);
        }
        statistics.setTowerCarneTodayWorkCount(statisticsSum2.getWorkCount());
      }
    }

    // 3.升降机统计
    // 查询所有的升降机机械
    MachineryDeviceVo elevatorMachineryDeviceVo = new MachineryDeviceVo();
    elevatorMachineryDeviceVo.setTypeCode("QUIP_SJJ_02");
    List<MachineryIotDeviceDto> elevatorMachineryIotDeviceDtos = machineryMonitorBiService
        .selectMachineryAndDeviceByCondition(elevatorMachineryDeviceVo);
    if (CollectionUtil.isNotEmpty(elevatorMachineryIotDeviceDtos)) {
      Date yesterday = cn.hutool.core.date.DateUtil.endOfDay(cn.hutool.core.date.DateUtil.yesterday());
      Date startTime = elevatorMachineryIotDeviceDtos.get(0).getDeviceRefTime();
      long days = cn.hutool.core.date.DateUtil.betweenDay(startTime, yesterday, true);

      // 所有项目
      Set<String> tenantIds = elevatorMachineryIotDeviceDtos.stream()
          .map(MachineryIotDeviceDto::getTenantId)
          .collect(Collectors.toSet());
      // 查询塔吊总数据
      ElevatorWorkStatisticsVO reqVO = new ElevatorWorkStatisticsVO();
      List<String> codeList = elevatorMachineryIotDeviceDtos.stream()
          .map(MachineryIotDeviceDto::getDeviceCode)
          .collect(Collectors.toList());

      reqVO.setCodeList(codeList);
      reqVO.setTenantIds(tenantIds);
      // 3.1 升降机日平均运行次数
      /**
       * 升降机日平均运行次数：
       *   【sum（每天的所有项目的运行次数之和/每天的升降机监测数量之和）】/升降机监测总天数
       *   PS：不包含今日
       */
      reqVO.setStartTime(DateUtil.getYYYYMMDDHHMMSSDate(startTime));
      reqVO.setEndTime(DateUtil.getYYYYMMDDHHMMSSDate(yesterday));
      List<ElevatorWorkStatisticsVO> statisticsByday = elevatorWorkRecordMapper
          .getStatisticsOrderByMachineryGlobal(reqVO);
      if (CollectionUtil.isNotEmpty(statisticsByday)) {
        Map<String, List<ElevatorWorkStatisticsVO>> dayMap = statisticsByday.stream()
            .collect(Collectors
                .groupingBy(ElevatorWorkStatisticsVO::getDay,
                    Collectors.mapping(m -> m, Collectors.toList())));

        double avgWorkCount = 0;
        for (Map.Entry<String, List<ElevatorWorkStatisticsVO>> entry : dayMap.entrySet()) {
          List<ElevatorWorkStatisticsVO> dayList = entry.getValue();
          Integer machineryNumByDay = machineryNumStatisticsService
              .findMachineryNumByDay(entry.getKey(), "QUIP_SJJ_02");
          Integer codeNum = dayList.size();
          if(null != machineryNumByDay && 0 != machineryNumByDay){
            codeNum = machineryNumByDay;
          }
          Integer total = dayList.stream().map(ElevatorWorkStatisticsVO::getWorkCount)
              .reduce(0, Integer::sum);
          avgWorkCount += NumberUtil.div(total.doubleValue(), codeNum.doubleValue(), 2);
        }
        if (avgWorkCount != 0 && days != 0) {
          statistics.setElevatorAvgDayWorkCount(NumberUtil.div(avgWorkCount, (double) days, 2));
        }

      }
      // 3.1 今日升降机运行次数=统计今日此时所有项目的升降机运行次数（=循环次数）
      reqVO.setStartTime(DateUtil.getYYYYMMDDHHMMSSDate(DateUtil.getCurrentDayMixDate()));
      reqVO.setEndTime(DateUtil.getYYYYMMDDHHMMSSDate(DateUtil.getCurrentDayMaxDate()));
      ElevatorWorkStatisticsVO statisticsSum2 = elevatorWorkRecordMapper
          .getStatisticsSum(reqVO);
      if (null != statisticsSum2) {
        statistics.setElevatorTodayWorkCount(statisticsSum2.getWorkCount());
      }
    }

    return statistics;
  }

  @Override
  public List<TowerCraneTopVO> getTowerCraneStatisticsTop(
      TowerCraneStatisticsVO statisticsVO) {
    List<TowerCraneTopVO> result = new ArrayList<>();
    // 1.查询所有的机械
    MachineryDeviceVo machineryDeviceVo = new MachineryDeviceVo();
    machineryDeviceVo.setTypeCode("QUIP_TSQZJ_01");
    List<MachineryIotDeviceDto> machineryIotDeviceDtos = machineryMonitorBiService
        .selectMachineryAndDeviceByCondition(machineryDeviceVo);
    if (CollectionUtil.isEmpty(machineryIotDeviceDtos)) {
      return null;
    }
    Map<String, List<MachineryIotDeviceDto>> machineryMap = machineryIotDeviceDtos.stream()
        .collect(Collectors
            .groupingBy(MachineryIotDeviceDto::getTenantId,
                Collectors.mapping(m -> m, Collectors.toList())));
    // 2.查询所有项目
    List<LinkappTenant> list = linkappTenantMapper.selectByProjectId(null);
    for (LinkappTenant p : list) {
      // 3.查询该项目的塔吊统计数据
      String tenantId = p.getId();
      if (machineryMap.containsKey(tenantId) && CollectionUtil
          .isNotEmpty(machineryMap.get(tenantId))) {
        List<MachineryIotDeviceDto> allMachineryIotDeviceDtos = machineryMap.get(tenantId);
        // 查询塔吊总数据
        TowerCraneWorkStatisticsVO reqVO = new TowerCraneWorkStatisticsVO();
        List<String> codeList = allMachineryIotDeviceDtos.stream()
            .map(MachineryIotDeviceDto::getDeviceCode)
            .collect(Collectors.toList());
        reqVO.setCodeList(codeList);
        reqVO.setTenantId(tenantId);
        reqVO.setStartTime(statisticsVO.getStartTime());
        reqVO.setEndTime(statisticsVO.getEndTime());
        TowerCraneWorkStatisticsVO statisticsSum = towerCraneWorkRecordMapper
            .getStatisticsSum(reqVO);
        if (null == statisticsSum) {
          result.add(new TowerCraneTopVO(p.getPlatformProjectName(), p.getProjectAmount(),
              p.getCreateTime(),
              0.00, 0.00));
        }
        Integer codeSize = codeList.size();
        Double workEfficiency = null != statisticsSum.getWorkEfficiency() ? NumberUtil.div(statisticsSum.getWorkEfficiency(), codeSize.doubleValue(), 2) : 0.00;
        Double workCount = null != statisticsSum.getWorkCount() ? NumberUtil.div(statisticsSum.getWorkCount().doubleValue(),codeSize.doubleValue(), 2) : 0.00;
        result.add(
            new TowerCraneTopVO(p.getPlatformProjectName(), p.getProjectAmount(), p.getCreateTime(),
                workCount, workEfficiency));
      }
    }
    // 4.按统计值排序
    if (CollectionUtil.isNotEmpty(result)) {
      if (statisticsVO.getOrderColumn() == 0) {
        result = result.stream().sorted(Comparator
            .comparing(TowerCraneTopVO::getWorkCount, Comparator.nullsLast(Double::compareTo).reversed())
            .thenComparing(TowerCraneTopVO::getProjectAmount, Comparator.nullsLast(Double::compareTo).reversed())
            .thenComparing(TowerCraneTopVO::getCreateTime,
                Comparator.nullsLast(Date::compareTo).reversed())).collect(Collectors.toList());//先以工作次数降序,再进行金额降序,再进行创建时间降序
      } else {
        result = result.stream().sorted(Comparator
            .comparing(TowerCraneTopVO::getWorkEfficiency, Comparator.nullsLast(Double::compareTo).reversed())
            .thenComparing(TowerCraneTopVO::getProjectAmount, Comparator.nullsLast(Double::compareTo).reversed())
            .thenComparing(TowerCraneTopVO::getCreateTime,
                Comparator.nullsLast(Date::compareTo).reversed())).collect(Collectors.toList());//先以工效降序,再进行金额降序,再进行创建时间降序
      }

    }
    return result;
  }

  @Override
  public List<ElevatorTopVO> getElevatorStatisticsTop(ElevatorStatisticsVO statisticsVO) {
    List<ElevatorTopVO> result = new ArrayList<>();
    // 1.查询所有的机械
    MachineryDeviceVo machineryDeviceVo = new MachineryDeviceVo();
    machineryDeviceVo.setTypeCode("QUIP_SJJ_02");
    List<MachineryIotDeviceDto> machineryIotDeviceDtos = machineryMonitorBiService
        .selectMachineryAndDeviceByCondition(machineryDeviceVo);
    if (CollectionUtil.isEmpty(machineryIotDeviceDtos)) {
      return null;
    }
    Map<String, List<MachineryIotDeviceDto>> machineryMap = machineryIotDeviceDtos.stream()
        .collect(Collectors
            .groupingBy(MachineryIotDeviceDto::getTenantId,
                Collectors.mapping(m -> m, Collectors.toList())));
    // 2.查询所有项目
    List<LinkappTenant> list = linkappTenantMapper.selectByProjectId(null);
    for (LinkappTenant p : list) {
      // 3.查询该项目的升降机统计数据
      String tenantId = p.getId();
      if (null != machineryMap && machineryMap.containsKey(tenantId) && CollectionUtil
          .isNotEmpty(machineryMap.get(tenantId))) {
        List<MachineryIotDeviceDto> allMachineryIotDeviceDtos = machineryMap.get(tenantId);
        // 查询升降机总数据
        ElevatorWorkStatisticsVO reqVO = new ElevatorWorkStatisticsVO();
        List<String> codeList = allMachineryIotDeviceDtos.stream()
            .map(MachineryIotDeviceDto::getDeviceCode)
            .collect(Collectors.toList());
        reqVO.setCodeList(codeList);
        reqVO.setTenantId(tenantId);
        reqVO.setStartTime(statisticsVO.getStartTime());
        reqVO.setEndTime(statisticsVO.getEndTime());
        ElevatorWorkStatisticsVO statisticsSum = elevatorWorkRecordMapper.getStatisticsSum(reqVO);
        if (null == statisticsSum) {
          result.add(
              new ElevatorTopVO(p.getPlatformProjectName(), p.getProjectAmount(), p.getCreateTime(),
                  0.00, 0.00));
        }
        Integer codeSize = codeList.size();
        Double weight = null != statisticsSum.getWeight() ? NumberUtil
            .div(statisticsSum.getWeight(),codeSize.doubleValue(), 2) : 0.00;
        Double workCount = null != statisticsSum.getWorkCount() ? NumberUtil
            .div(statisticsSum.getWorkCount().doubleValue(), codeSize.doubleValue(), 2) : 0.00;
        result.add(
            new ElevatorTopVO(p.getPlatformProjectName(), p.getProjectAmount(), p.getCreateTime(),
                workCount, weight));
      }
    }
    // 4.按统计值排序
    if (CollectionUtil.isNotEmpty(result)) {
      if (statisticsVO.getOrderColumn() == 0) {
        result = result.stream().sorted(Comparator
            .comparing(ElevatorTopVO::getWorkCount, Comparator.nullsLast(Double::compareTo).reversed())
            .thenComparing(ElevatorTopVO::getProjectAmount, Comparator.nullsLast(Double::compareTo).reversed())
            .thenComparing(ElevatorTopVO::getCreateTime,
                Comparator.nullsLast(Date::compareTo).reversed())).collect(Collectors.toList());//先以工作次数降序,再进行金额降序,再进行创建时间降序
      } else {
        result = result.stream().sorted(Comparator
            .comparing(ElevatorTopVO::getWeight, Comparator.nullsLast(Double::compareTo).reversed())
            .thenComparing(ElevatorTopVO::getProjectAmount, Comparator.nullsLast(Double::compareTo).reversed())
            .thenComparing(ElevatorTopVO::getCreateTime,
                Comparator.nullsLast(Date::compareTo).reversed())).collect(Collectors.toList());//先以运行重量降序,再进行金额降序,再进行创建时间降序
      }

    }
    return result;
  }

  @Override
  public List<ProjectStatisticsVO> selectProjectStatisticList(
      ProjectStatisticsVO projectStatisticsVO) {
    List<ProjectStatisticsVO> result = new ArrayList<>();
    // 1.查询所有机械记录
    Map<String, List<MachineryRecord>> machineryMap = null;
    QueryWrapper<MachineryRecord> queryWrapper = new QueryWrapper<>();

    // 5.查询所有项目
    QueryWrapper<LinkappTenant> tenantQueryWrapper = new QueryWrapper<>();
    if (StringUtils.isNotBlank(projectStatisticsVO.getProjectName())) {
      List<String> tenantIds = new LambdaQueryChainWrapper<>(linkappTenantMapper).like(LinkappTenant::getPlatformProjectName,
              projectStatisticsVO.getProjectName()).select(LinkappTenant::getId).list().stream().map(LinkappTenant::getId).collect(Collectors.toList());
        if (CollectionUtil.isNotEmpty(tenantIds)) {
          queryWrapper.in("tenant_id_", tenantIds);
          tenantQueryWrapper.in("id", tenantIds);
        }else{
            return Collections.emptyList();
        }
    }
    List<MachineryRecord> machineryRecords = machineryRecordMapper.selectList(queryWrapper);
    if (CollectionUtil.isNotEmpty(machineryRecords)) {
      machineryMap = machineryRecords.stream()
          .collect(Collectors
              .groupingBy(MachineryRecord::getTenantId,
                  Collectors.mapping(m -> m, Collectors.toList())));
    }

    // 2.查询所有的机械检测数 塔吊
    Map<String, List<MachineryIotDeviceDto>> towerMachineryMap = null;
    MachineryDeviceVo machineryDeviceVo = new MachineryDeviceVo();
    machineryDeviceVo.setTypeCode("QUIP_TSQZJ_01");
    List<MachineryIotDeviceDto> towerMachineryIotDeviceDtos = machineryMonitorBiService
        .selectMachineryAndDeviceByCondition(machineryDeviceVo);
    if (CollectionUtil.isNotEmpty(towerMachineryIotDeviceDtos)) {
      towerMachineryMap = towerMachineryIotDeviceDtos.stream()
          .collect(Collectors
              .groupingBy(MachineryIotDeviceDto::getTenantId,
                  Collectors.mapping(m -> m, Collectors.toList())));
    }

    // 3.查询所有的机械检测数 升降机
    Map<String, List<MachineryIotDeviceDto>> elevatorMachineryMap = null;
    machineryDeviceVo.setTypeCode("QUIP_SJJ_02");
    List<MachineryIotDeviceDto> elevatorMachineryIotDeviceDtos = machineryMonitorBiService
        .selectMachineryAndDeviceByCondition(machineryDeviceVo);
    if (CollectionUtil.isNotEmpty(elevatorMachineryIotDeviceDtos)) {
      elevatorMachineryMap = elevatorMachineryIotDeviceDtos.stream()
          .collect(Collectors
              .groupingBy(MachineryIotDeviceDto::getTenantId,
                  Collectors.mapping(m -> m, Collectors.toList())));
    }

    // 4.查找机械统计
    MachineryStatisticsVO machineryStatistics = getMachineryStatistics();

    tenantQueryWrapper.orderByDesc("project_amount","create_time");
    List<LinkappTenant> list = linkappTenantMapper.selectList(tenantQueryWrapper);
    for(LinkappTenant p : list){
      String tenantId = p.getId();
      ProjectStatisticsVO statisticsVO = new ProjectStatisticsVO();
      statisticsVO.setProjecId(tenantId);
      statisticsVO.setProjectName(p.getPlatformProjectName());
      statisticsVO.setTotal(0);
      statisticsVO.setMonitoringNum(0);
      statisticsVO.setTowerCarneAvgEfficiency(0.0);
      statisticsVO.setTowerCarneTodayAvgWorkCount(0.0);
      statisticsVO.setElevatorTodayAvgWorkCount(0.0);

      // 判断是否有机械
      if (null != machineryMap && machineryMap.containsKey(tenantId) && CollectionUtil
          .isNotEmpty(machineryMap.get(tenantId))) {
        List<MachineryRecord> machinerys = machineryMap.get(tenantId);
        statisticsVO.setTotal(machinerys.size());
        int monitoringNum = 0;
        // 判断是否有机械 塔吊
        if (null != towerMachineryMap && towerMachineryMap.containsKey(tenantId) && CollectionUtil
            .isNotEmpty(towerMachineryMap.get(tenantId))) {
          List<MachineryIotDeviceDto> towerMachinerys = towerMachineryMap.get(tenantId);
          Date yesterday = cn.hutool.core.date.DateUtil.endOfDay(cn.hutool.core.date.DateUtil.yesterday());
          Date startTime = towerMachinerys.get(0).getDeviceRefTime();
          monitoringNum += towerMachinerys.size();

          // 查询塔吊总数据
          TowerCraneWorkStatisticsVO reqVO = new TowerCraneWorkStatisticsVO();
          List<String> codeList = towerMachinerys.stream()
              .map(MachineryIotDeviceDto::getDeviceCode)
              .collect(Collectors.toList());
          reqVO.setCodeList(codeList);
          reqVO.setTenantId(tenantId);
          reqVO.setStartTime(DateUtil.getYYYYMMDDHHMMSSDate(startTime));
          reqVO.setEndTime(DateUtil.getYYYYMMDDHHMMSSDate(yesterday));
          TowerCraneWorkStatisticsVO statisticsSum = towerCraneWorkRecordMapper
              .getStatisticsSum(reqVO);
          if (null != statisticsSum) {
            Integer codeSize = codeList.size();
            if (statisticsSum.getWorkEfficiency() != null) {
              double towerCarneAvgEfficiency = NumberUtil
                  .div(statisticsSum.getWorkEfficiency(), codeSize.doubleValue(), 2);
              statisticsVO.setTowerCarneAvgEfficiency(towerCarneAvgEfficiency);
            }
          }
          // 查询塔吊今日数据
          reqVO.setStartTime(projectStatisticsVO.getStartTime());
          reqVO.setEndTime(projectStatisticsVO.getEndTime());
          TowerCraneWorkStatisticsVO statisticsSumToday = towerCraneWorkRecordMapper
              .getStatisticsSum(reqVO);
          if (null != statisticsSumToday) {
            Integer codeSize = codeList.size();
            if (statisticsSumToday.getWorkCount() != null&&statisticsSumToday.getWorkCount() != 0) {
              double towerCarneTodayAvgWorkCount = NumberUtil
                  .div(statisticsSumToday.getWorkCount().doubleValue(), codeSize.doubleValue(), 2);
              statisticsVO.setTowerCarneTodayAvgWorkCount(towerCarneTodayAvgWorkCount);
            }
          }
        }
        // 判断是否有机械 升降机
        if (null != elevatorMachineryMap && elevatorMachineryMap.containsKey(tenantId)
            && CollectionUtil.isNotEmpty(elevatorMachineryMap.get(tenantId))) {
          List<MachineryIotDeviceDto> elevatorMachinerys = elevatorMachineryMap.get(tenantId);
          monitoringNum += elevatorMachinerys.size();

          // 查询升降机总数据
          ElevatorWorkStatisticsVO reqVO = new ElevatorWorkStatisticsVO();
          List<String> codeList = elevatorMachinerys.stream()
              .map(MachineryIotDeviceDto::getDeviceCode)
              .collect(Collectors.toList());
          reqVO.setCodeList(codeList);
          reqVO.setTenantId(tenantId);
          reqVO.setStartTime(projectStatisticsVO.getStartTime());
          reqVO.setEndTime(projectStatisticsVO.getEndTime());
          ElevatorWorkStatisticsVO statisticsSum = elevatorWorkRecordMapper.getStatisticsSum(reqVO);
          if (null != statisticsSum) {
            Integer codeSize = codeList.size();
            if (statisticsSum.getWorkCount() != null&&statisticsSum.getWorkCount() != 0) {
              double elevatorTodayAvgWorkCount = NumberUtil
                  .div(statisticsSum.getWorkCount().doubleValue(), codeSize.doubleValue(), 2);
              statisticsVO.setElevatorTodayAvgWorkCount(elevatorTodayAvgWorkCount);
            }
          }
        }
        if (null != machineryStatistics && monitoringNum > 0) {
          if(null != machineryStatistics.getTowerCarneAvgEfficiency()){
            Double towerCarneAvgEfficiencyAll = machineryStatistics.getTowerCarneAvgEfficiency();
            Double towerCarneAvgEfficiencyDifferent = 0.0;
            double sub = NumberUtil
                .sub(statisticsVO.getTowerCarneAvgEfficiency(), towerCarneAvgEfficiencyAll, 2);
            towerCarneAvgEfficiencyDifferent = NumberUtil.div(sub,towerCarneAvgEfficiencyAll,2);
            statisticsVO.setTowerCarneAvgEfficiencyDifferent(towerCarneAvgEfficiencyDifferent);
          }
          if(null != machineryStatistics.getTowerCarneAvgDayWorkCount()){
            Double towerCarneAvgDayWorkCountAll = machineryStatistics.getTowerCarneAvgDayWorkCount();
            if(null != towerCarneAvgDayWorkCountAll && 0 != towerCarneAvgDayWorkCountAll){
              Double towerCarneAvgWorkCountDifferent = 0.0;
              double sub = NumberUtil
                  .sub(statisticsVO.getTowerCarneTodayAvgWorkCount(), towerCarneAvgDayWorkCountAll, 2);
              towerCarneAvgWorkCountDifferent = NumberUtil.div(sub,towerCarneAvgDayWorkCountAll,2);
              statisticsVO.setTowerCarneAvgWorkCountDifferent(towerCarneAvgWorkCountDifferent);
            }
          }
          if(null != machineryStatistics.getElevatorAvgDayWorkCount()){
            Double elevatorTodayAvgWorkCountAll = machineryStatistics.getElevatorAvgDayWorkCount();
            Double elevatorAvgWorkCountDifferent = 0.0;
            if(null != elevatorTodayAvgWorkCountAll && 0 != elevatorTodayAvgWorkCountAll){
              double sub = NumberUtil
                  .sub(statisticsVO.getElevatorTodayAvgWorkCount(), elevatorTodayAvgWorkCountAll, 2);
              elevatorAvgWorkCountDifferent = NumberUtil.div(sub,elevatorTodayAvgWorkCountAll,2);
              statisticsVO.setElevatorAvgWorkCountDifferent(elevatorAvgWorkCountDifferent);
            }

          }
        }


        statisticsVO.setMonitoringNum(monitoringNum);
      }


      result.add(statisticsVO);
    }
    return result;
  }

  private static final String machineryRuleConfigPrefixKey = "RULE_ALARM_MACHINERY_TYPE_";

  @Resource
  private AlarmMapper alarmMapper;

  @Override
  public List<MachineryWarnGroupTypeVO> countMachineryWarnGroupType(
      MachineryDeviceVo machineryDeviceVo) {
    List<MachineryWarnGroupTypeVO> result = new ArrayList<>();
    String key = machineryRuleConfigPrefixKey + machineryDeviceVo.getTypeCode();
    List<String> warnTypeNamesByKey = DeviceUtil.getDeviceTypeNamesByKey(key, null);
    if(CollectionUtil.isEmpty(warnTypeNamesByKey)){
      return null;
    }
    warnTypeNamesByKey.forEach(p->{
      result.add(new MachineryWarnGroupTypeVO(p,0));
    });
    AlarmDeviceVo alarmDeviceVo = new AlarmDeviceVo();
    alarmDeviceVo.setWarmNameList(warnTypeNamesByKey);
    List<MachineryWarnGroupTypeVO> warnGroupTypeVOS = alarmMapper
        .countAlarmByWarnTypeGlobal(alarmDeviceVo);
    if(CollectionUtil.isNotEmpty(warnGroupTypeVOS)){
      Map<String, MachineryWarnGroupTypeVO> warnGroupTypeVOMap = warnGroupTypeVOS.stream()
          .collect(Collectors.toMap(MachineryWarnGroupTypeVO::getWarnName,
              p -> p));
      result.forEach(p->{
        MachineryWarnGroupTypeVO machineryWarnGroupTypeVO = warnGroupTypeVOMap.get(p.getWarnName());
        if(null != machineryWarnGroupTypeVO){
          p.setNum(machineryWarnGroupTypeVO.getNum());
        }
      });
    }
    return result;
  }

  @Override
  public List<ProjectWarnStatsticsVO> getProjectWarnStatisticTop(MachineryDeviceVo machineryDeviceVo) {

    List<ProjectWarnStatsticsVO> result = new ArrayList<>();
    // 1.查询所有告警
    String key = machineryRuleConfigPrefixKey + machineryDeviceVo.getTypeCode();
    List<String> warnTypeNamesByKey = DeviceUtil.getDeviceTypeNamesByKey(key, null);
    if(CollectionUtil.isEmpty(warnTypeNamesByKey)){
      return null;
    }
    Map<String, ProjectWarnStatsticsVO> projectWarnStatsticsVOMap = null;
    AlarmDeviceVo alarmDeviceVo = new AlarmDeviceVo();
    alarmDeviceVo.setWarmNameList(warnTypeNamesByKey);
    List<ProjectWarnStatsticsVO> projectWarnStatsticsVOS = alarmMapper
        .countAlarmByProjectGlobal(alarmDeviceVo);
    if(CollectionUtil.isNotEmpty(projectWarnStatsticsVOS)){
      projectWarnStatsticsVOMap = projectWarnStatsticsVOS.stream().collect(Collectors.toMap(ProjectWarnStatsticsVO::getProjecId,
          p -> p));
    }

    // 2.查询所有的机械检测数
    Map<String, List<MachineryIotDeviceDto>> machineryMap = null;
    List<MachineryIotDeviceDto> towerMachineryIotDeviceDtos = machineryMonitorBiService
        .selectMachineryAndDeviceByCondition(machineryDeviceVo);
    if (CollectionUtil.isNotEmpty(towerMachineryIotDeviceDtos)) {
      machineryMap = towerMachineryIotDeviceDtos.stream()
          .collect(Collectors
              .groupingBy(MachineryIotDeviceDto::getTenantId,
                  Collectors.mapping(m -> m, Collectors.toList())));
    }

    // 3.查询项目列表
    QueryWrapper<LinkappTenant> tenantQueryWrapper = new QueryWrapper<>();
    tenantQueryWrapper.orderByDesc("project_amount","create_time");
    List<LinkappTenant> list = linkappTenantMapper.selectList(tenantQueryWrapper);
    for(LinkappTenant p : list){
      double days = 0d;
      String tenantId = p.getId();
      if(machineryMap.containsKey(tenantId)&&CollectionUtil.isNotEmpty(machineryMap.get(tenantId))){
        List<MachineryIotDeviceDto> machineryIotDeviceDtos = machineryMap.get(tenantId);
        Date startTime = machineryIotDeviceDtos.get(0).getDeviceRefTime();
        days = cn.hutool.core.date.DateUtil.betweenDay(startTime, new Date(), true);
      }
      if(null != projectWarnStatsticsVOMap&&projectWarnStatsticsVOMap.containsKey(tenantId)){
        ProjectWarnStatsticsVO projectWarnStatsticsVO = projectWarnStatsticsVOMap.get(tenantId);
        projectWarnStatsticsVO.setProjectName(p.getPlatformProjectName());
        projectWarnStatsticsVO.setDays((int)days);
        result.add(projectWarnStatsticsVO);
      }
    }
    // 4.按统计值排序
    if (CollectionUtil.isNotEmpty(result)) {
      result = result.stream().sorted(Comparator
          .comparing(ProjectWarnStatsticsVO::getWarnNum,
              Comparator.nullsLast(Integer::compareTo).reversed())).collect(Collectors.toList());//按告警排序
    }
    return result;
  }

  public static void main(String[] args) {
    Double elevatorTodayAvgWorkCountAll = 10.0;
    Double elevatorAvgWorkCountDifferent = 0.0;
    double sub = NumberUtil
        .sub(10.0, elevatorTodayAvgWorkCountAll, 2);
    elevatorAvgWorkCountDifferent = NumberUtil.div(sub,elevatorTodayAvgWorkCountAll,2);
    System.out.println(elevatorAvgWorkCountDifferent);
  }
}
